#include "tictactoe.h"
#include <QDebug>
#include <QRandomGenerator>

TicTacToe::TicTacToe(QWidget *parent)
    : QWidget(parent), playerTurn(true),enableComputerOpponent(false), moves(0), playerScore(0), computerScore(0) // 初始化比分
{
    // 初始化 boardState_byAPI 为 3x3 的二维向量，初始值都为 0
    boardState_byAPI.resize(3);
    for(int i = 0; i < 3; ++i){
        boardState_byAPI[i].resize(3);
    }
    setupBoard();
}

void TicTacToe::setupBoard()
{
    gridLayout = new QGridLayout(this);
    // 创建得分和局数标签
    playerScoreLabel = new QLabel("玩家: 0", this);
    computerScoreLabel = new QLabel("电脑: 0", this);
    gameCountLabel = new QLabel("总对局: 0", this);
    // 将标签添加到布局中
    gridLayout->addWidget(playerScoreLabel, 0, 0);
    gridLayout->addWidget(computerScoreLabel, 0, 1);
    gridLayout->addWidget(gameCountLabel, 0, 2);
    for (int i = 0; i < 9; ++i) {
        QPushButton *tile = new QPushButton(this);
        tile->setFixedSize(100, 100);
        // 设置样式表
        tile->setStyleSheet(
            "QPushButton {"
            "   background-color: #f0f0f0;"  // 浅灰色背景
            "   border: 2px solid #ddd;"     // 浅灰色边框
            "   border-radius: 10px;"       // 圆角
            "   font-size: 24px;"          // 更大的字体
            "   font-weight: bold;"       // 粗体
            "   color: red;"              // 字体颜色为红色
            "}"
            "QPushButton:hover {"
            "   background-color: #e0e0e0;"  // 鼠标悬停时更浅的灰色
            "}"
            "QPushButton:pressed {"
            "   background-color: #d0d0d0;"  // 点击时更深的灰色
            "   border: 2px solid #ccc;"     // 边框颜色加深
            "}"
        );
        tiles.append(tile);
        connect(tile, &QPushButton::clicked, this, &TicTacToe::onTileClicked);
        gridLayout->addWidget(tile, (i+6) / 3, i % 3);
    }
    normalButton = new QPushButton("普通模式",this);
    masterButton = new QPushButton("大师模式",this);
    normalButton->setEnabled(false);
    masterButton->setEnabled(true);
     //你也可以为标签也设置一下样式
    QString labelStyle =
          "QLabel { font-size: 25px; margin-top: 10px; }";

    playerScoreLabel->setStyleSheet(labelStyle);
    computerScoreLabel->setStyleSheet(labelStyle);
    gameCountLabel->setStyleSheet(labelStyle);

    gridLayout->addWidget(normalButton,1,0);
    gridLayout->addWidget(masterButton,1,2);
    setLayout(gridLayout);

    // 连接信号和槽 (使用 lambda 表达式，C++11 及以上)
    connect(normalButton, &QPushButton::clicked, this, [this]() {
        Normal_Master_Flag = false;
        normalButton->setEnabled(false);
        masterButton->setEnabled(true);
    });

    connect(masterButton, &QPushButton::clicked, this, [this]() {
        Normal_Master_Flag = true;
        normalButton->setEnabled(true);
        masterButton->setEnabled(false);
    });
}

void TicTacToe::onTileClicked()
{
    QPushButton *button = qobject_cast<QPushButton*>(sender());
    if (button && button->text().isEmpty()) {
        button->setText(playerTurn ? "X" : "O");
        playerTurn = !playerTurn;
        ++moves;
        checkWin();

        if (!playerTurn && enableComputerOpponent) { // 如果是电脑回合且开启人机对战
            QVector<QVector<int>> boardState(3, QVector<int>(3, 0));
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    if (tiles[i * 3 + j]->text() == "X") {
                        boardState[i][j] = 1;
                    } else if (tiles[i * 3 + j]->text() == "O") {
                        boardState[i][j] = 2;
                    }
                }
            }

            int bestMove = findBestMove(boardState);

            if (bestMove != -1) {
                int row = bestMove / 3;
                int col = bestMove % 3;
                tiles[row * 3 + col]->setText("O");
                playerTurn = !playerTurn;
                ++moves;
                checkWin();
            }
        }
    }
}

void TicTacToe::checkWin()
{
    static const int winCombinations[8][3] = {
        {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, // Rows
        {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, // Columns
        {0, 4, 8}, {2, 4, 6}            // Diagonals
    };

    for (const auto &combination : winCombinations) {
        if (tiles[combination[0]]->text() == tiles[combination[1]]->text() &&
            tiles[combination[1]]->text() == tiles[combination[2]]->text() &&
            !tiles[combination[0]]->text().isEmpty()) {
            QString winner = tiles[combination[0]]->text();
            qDebug() << winner << " wins!";
            // 更新比分
            if (winner == "X") {
                ++playerScore;
                whoWin = 1;
            } else if (winner == "O") {
                ++computerScore;
                whoWin = 2;
            }
            // 更新得分标签
            updateScoreLabels();
            // Reset the game
            resetBoard();
            GameCount++;
        }
    }

    if (moves == 9) {
        qDebug() << "Draw!";
        // 更新得分标签
        updateScoreLabels();
        // Reset the game
        resetBoard();
        GameCount++;
        whoWin = 0;
        return;
    }
}
/*
你可以在其他地方调用 updateBoard 函数来更新棋盘状态，例如：
QVector<QVector<int>> boardState = {
    {1, 0, 2},
    {0, 1, 0},
    {2, 0, 1}
};

ticTacToeInstance->updateBoard(boardState);

棋盘将会根据 boardState 的值更新显示内容
*/
void TicTacToe::updateBoard(const QVector<QVector<int>>& boardState)
{
    if (boardState.size() != 3) {
        qWarning() << "Invalid board state size. Expected 3x3.";
        return;
    }

    for (int i = 0; i < 3; ++i) {
        if (boardState[i].size() != 3) {
            qWarning() << "Invalid board state size. Expected 3x3.";
            return;
        }
        for (int j = 0; j < 3; ++j) {
            int index = i * 3 + j;
            switch (boardState[i][j]) {
                case 0:
                    tiles[index]->setText("");
                    break;
                case 1:
                    tiles[index]->setText("X");
                    break;
                case 2:
                    tiles[index]->setText("O");
                    break;
                default:
                    qWarning() << "Invalid value in board state. Expected 0, 1, or 2.";
                    break;
            }
        }
    }
    playerTurn = !playerTurn;
    ++moves;
    checkWin();
}

/*
重置棋局
*/
void TicTacToe::resetBoard()
{
    for (QPushButton *tile : tiles) {
        tile->setText("");
    }
    playerTurn = true;
    moves = 0;
    // 更新得分标签
    updateScoreLabels();
}

/*
你可以在其他地方调用 getScores 函数来获取当前的比分，例如：
QPair<int, int> scores = ticTacToeInstance->getScores();
qDebug() << "Player Score:" << scores.first << "Computer Score:" << scores.second;
*/
QPair<int, int> TicTacToe::getScores() const
{
    return QPair<int, int>(playerScore, computerScore);
}
/*
你可以在其他地方调用 isPlayerMove 函数来检查玩家是否下棋，例如：
QVector<QVector<int>> previousBoard = {
    {0, 0, 0},
    {0, 0, 0},
    {0, 0, 0}
};

QVector<QVector<int>> currentBoard = {
    {1, 0, 0},
    {0, 0, 0},
    {0, 0, 0}
};

bool isPlayer = ticTacToeInstance->isPlayerMove(previousBoard, currentBoard);
qDebug() << "Is Player Move:" << isPlayer;
*/
int TicTacToe::isPlayerMove(const QVector<QVector<int>>& previousBoard, const QVector<QVector<int>>& currentBoard)
{
    // 检查两个棋盘的大小是否符合要求
    if (previousBoard.size() != 3 || currentBoard.size() != 3) {
        qWarning() << "Invalid board state size. Expected" << 3 << "x" << 3 << ".";
        return -1;
    }

    qDebug()<<"上次棋盘";
    printBoard(previousBoard);
    qDebug()<<"AI识别的当前棋盘";
    printBoard(currentBoard);

    int changeCount = 0;
    int changeRow = -1;
    int changeCol = -1;
    for (int i = 0; i < 3; ++i) {
        // 检查每个子向量的大小是否符合要求
        if (previousBoard[i].size() != 3 || currentBoard[i].size() != 3) {
            qWarning() << "Invalid board state size. Expected" << 3 << "x" << 3 << ".";
            return -1;
        }
        for (int j = 0; j < 3; ++j) {
            if (previousBoard[i][j] != currentBoard[i][j]) {
                ++changeCount;
                changeRow = i;
                changeCol = j;
            }
            // 如果不同位置数量已经大于 1，说明玩家挪棋子了，直接返回 false
            if (changeCount > 1) {
                qDebug() << "不同位置数量已经大于 1，说明玩家挪棋子了";
                return 2;
            }
        }
    }
    // 如果不同位置数量小于 1，说明玩家没下棋，返回 false
    if (changeCount < 1) {
        qDebug() << "不同位置数量小于 1，说明玩家没下棋";
        return 3;
    }
    // 不同位置数量等于 1 的情况下，检查是否是从 0 变为 1
    if (previousBoard[changeRow][changeCol] == 0 && currentBoard[changeRow][changeCol] == 1)
    {
        qDebug() << "玩家正确下棋";
        return 1;
    }
    else
    {
        //玩家下错棋子了
        qDebug() << "玩家错误使用了O棋";
        return 4;
    }
    return -1;
}
// 新增函数：返回当前的局数
int TicTacToe::getGameCount() const
{
    return GameCount;
}
//返回当前用户X？  O?
bool TicTacToe::getplayerTurn()
{
    return playerTurn;
}
void TicTacToe::updateScoreLabels()
{
    playerScoreLabel->setText(QString("玩家: %1").arg(playerScore));
    computerScoreLabel->setText(QString("电脑: %1").arg(computerScore));
    gameCountLabel->setText(QString("总对局: %1").arg(getGameCount()));
}

/*
findBestMove 函数是专门为电脑玩家（即“O”）寻找最佳落子位置的。以下是详细的实现说明和代码。

实现步骤
检查是否存在可以让电脑立即获胜的落子位置。
检查是否存在玩家下一步就能获胜的位置，若有则占据该位置以阻止玩家获胜。
如果中心位置未被占据，则选择该位置。
随机选择一个未被占据的角落位置。
随机选择一个剩余的可用位置。
如果没有可用位置，则返回 -1。
*/
int TicTacToe::findBestMove_normal(const QVector<QVector<int>>& boardState)
{
    // 检查两个棋盘的大小是否符合要求
    if (boardState.size() != 3) {
        qWarning() << "Invalid board state size. Expected 3x3.";
        return -1;
    }

    // 检查每个子向量的大小是否符合要求
    for (int i = 0; i < 3; ++i) {
        if (boardState[i].size() != 3) {
            qWarning() << "Invalid board state size. Expected 3x3.";
            return -1;
        }
    }

    // Helper function to check if a player can win with a given move
    auto canWin = [&](int player, int& row, int& col) -> bool {
        static const int winCombinations[8][3] = {
            {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, // Rows
            {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, // Columns
            {0, 4, 8}, {2, 4, 6}            // Diagonals
        };

        for (const auto& combination : winCombinations) {
            int count = 0;
            int emptyCount = 0;
            int emptyRow = -1;
            int emptyCol = -1;
            for (int k = 0; k < 3; ++k) {
                int i = combination[k] / 3;
                int j = combination[k] % 3;
                if (boardState[i][j] == player) {
                    ++count;
                } else if (boardState[i][j] == 0) {
                    ++emptyCount;
                    emptyRow = i;
                    emptyCol = j;
                }
            }
            if (count == 2 && emptyCount == 1) {
                row = emptyRow;
                col = emptyCol;
                return true;
            }
        }
        return false;
    };

    // 1. Check for a winning move for the computer
    int row, col;
    if (canWin(2, row, col)) {
        qDebug() << "Computer can win at (" << row << ", " << col << ")";
        return row * 3 + col;
    }

    // 2. Check for a blocking move for the player
    if (canWin(1, row, col)) {
        qDebug() << "Computer blocks player at (" << row << ", " << col << ")";
        return row * 3 + col;
    }

    // 3. Check for the center position
    if (boardState[1][1] == 0) {
        qDebug() << "Computer moves to center (1, 1)";
        return 4;
    }

    // 5. Check for a random available position
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            if (boardState[i][j] == 0) {
                qDebug() << "Computer moves to random position (" << i << ", " << j << ")";
                return i * 3 + j;
            }
        }
    }

    // 6. No available position
    qDebug() << "No available position.";
    return -1;
}

int TicTacToe::findBestMove_master(const QVector<QVector<int>>& boardState)
{
    // 检查两个棋盘的大小是否符合要求
    if (boardState.size() != 3) {
        qWarning() << "Invalid board state size. Expected 3x3.";
        return -1;
    }

    // 检查每个子向量的大小是否符合要求
    for (int i = 0; i < 3; ++i) {
        if (boardState[i].size() != 3) {
            qWarning() << "Invalid board state size. Expected 3x3.";
            return -1;
        }
    }

    // Helper function to check if a player can win with a given move
    auto canWin = [&](int player, int& row, int& col) -> bool {
        static const int winCombinations[8][3] = {
            {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, // Rows
            {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, // Columns
            {0, 4, 8}, {2, 4, 6}            // Diagonals
        };

        for (const auto& combination : winCombinations) {
            int count = 0;
            int emptyCount = 0;
            int emptyRow = -1;
            int emptyCol = -1;
            for (int k = 0; k < 3; ++k) {
                int i = combination[k] / 3;
                int j = combination[k] % 3;
                if (boardState[i][j] == player) {
                    ++count;
                } else if (boardState[i][j] == 0) {
                    ++emptyCount;
                    emptyRow = i;
                    emptyCol = j;
                }
            }
            if (count == 2 && emptyCount == 1) {
                row = emptyRow;
                col = emptyCol;
                return true;
            }
        }
        return false;
    };

    // 1. Check for a winning move for the computer
    int row, col;
    if (canWin(2, row, col)) {
        qDebug() << "Computer can win at (" << row << ", " << col << ")";
        return row * 3 + col;
    }

    // 2. Check for a blocking move for the player
    if (canWin(1, row, col)) {
        qDebug() << "Computer blocks player at (" << row << ", " << col << ")";
        return row * 3 + col;
    }

    // 3. Check for the center position
    if (boardState[1][1] == 0) {
        qDebug() << "Computer moves to center (1, 1)";
        return 4;
    }

    // 4. Check for a corner position
    static const std::vector<std::pair<int, int>> corners = {{0, 0}, {0, 2}, {2, 0}, {2, 2}};
    for (const auto& corner : corners) {
        if (boardState[corner.first][corner.second] == 0) {
            qDebug() << "Computer moves to corner (" << corner.first << ", " << corner.second << ")";
            return corner.first * 3 + corner.second;
        }
    }

    // 5. Check for a random available position
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            if (boardState[i][j] == 0) {
                qDebug() << "Computer moves to random position (" << i << ", " << j << ")";
                return i * 3 + j;
            }
        }
    }

    // 6. No available position
    qDebug() << "No available position.";
    return -1;
}

void TicTacToe::parseResponseToBoardState_byAPI(const QString& response) 
{
    // 确保 boardState_byAPI 是一个 3x3 的数组
    boardState_byAPI.resize(3); // 调整大小为 3
    for (int i = 0; i < 3; ++i) {
        boardState_byAPI[i].resize(3); // 每个子向量大小为 3，初始值为 0
    }
    // 遍历字符串并填充 boardState_byAPI
    for (int i = 0; i < 9; ++i) {
        int row = i / 3;
        int col = i % 3;
        QChar ch = response.at(i);
        QString charStr = QString(ch);
        if (charStr == "X") {
            boardState_byAPI[row][col] = 1;
        } else if (charStr == "O") {
            boardState_byAPI[row][col] = 2;
        } else if (charStr == "中") {
            boardState_byAPI[row][col] = 0;
        } else {
            qDebug() << "Invalid character in response:" << ch;
            return;
        }
    }
}
// 提供一个公共方法用于打印并获取转化后的二维数据
const QVector<QVector<int>>& TicTacToe::printAndGetBoardState(){
    return boardState_byAPI;
}
//打印棋盘
void TicTacToe::printBoard(const QVector<QVector<int>>& boardState)
{
    qDebug()<<boardState[0][0]<<boardState[0][1]<<boardState[0][2];
    qDebug()<<boardState[1][0]<<boardState[1][1]<<boardState[1][2];
    qDebug()<<boardState[2][0]<<boardState[2][1]<<boardState[2][2];
}
int TicTacToe::findBestMove(const QVector<QVector<int>>& boardState)
{
    if (Normal_Master_Flag) {
          // 假设有一个名为 findBestMove_master 的函数
          return  findBestMove_master(boardState);
    } else {
          // 假设有一个名为 findBestMove_normal 的函数
          return findBestMove_normal(boardState);
    }
    return -1;
}
